package cm.com.blackboard.DataModule4B2.customizeConfigUtils;

import java.beans.IntrospectionException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import blackboard.admin.data.datasource.DataSource;
import blackboard.data.BbObject;
import blackboard.persist.Id;
import cn.com.blackboard.DataModule4B2.BBDataUtils.DataSourceUtil;
import cn.com.blackboard.DataModule4B2.model.BaseModel;
import cn.com.blackboard.DataModule4B2.util.DataSourceModel;
import cn.com.blackboard.DataModule4B2.util.ExtentionModel;
import cn.com.blackboard.DataModule4B2.util.DataSourceModel.SourceType;

public class DataSourceKeyUtil {
private static final Logger logger = LoggerFactory.getLogger(DataSourceKeyUtil.class);
	
	static String profilepath=CommonConfigLoader.class.getClassLoader().getResource("/datasourcekeyMap.xml").getPath();
	//static String profilepath = System.getProperty("user.dir")+"/target/classes/datasourcekeyMap.xml";
       
	private static List<DataSourceModel> dataSourceModelList = new ArrayList<DataSourceModel> ();
	static { 
		try {
			dataSourceModelList = BaseXMLUtil.parseXML(profilepath, DataSourceModel.class);
		} catch (JDOMException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
	
	 public static boolean setAndPersistExtentionList(List<DataSourceModel> dsList){
		 dataSourceModelList = dsList;
			try {
				BaseXMLUtil.renderXML(profilepath, ExtentionModel.class, dataSourceModelList);
				return true;
			} catch (FileNotFoundException e) {
				e.printStackTrace();
				return false;
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			} catch (IllegalAccessException e) {
				e.printStackTrace();
				return false;
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
				return false;
			} catch (InvocationTargetException e) {
				e.printStackTrace();
				return false;
			} catch (IntrospectionException e) {
				e.printStackTrace();
				return false;
			}
		}
	
	public static List<DataSourceModel> getDataSourceModelList() {
		return dataSourceModelList;
	}

	public static void setDataSourceModelList(List<DataSourceModel> dataSourceModelList) {
		DataSourceKeyUtil.dataSourceModelList = dataSourceModelList;
	}

	private static DataSourceModel findDataSourceModelByClsNames(String bbClsName, String modelClsName){
		for(DataSourceModel dsModel:dataSourceModelList){
			if(dsModel.getBbClsName().equals(bbClsName)&&dsModel.getModelClsName().equals(modelClsName))
				return dsModel;
		}
		return null;
	}
	
	private static String dataSourceId = "defaultId";
	private static String description = "默认id";

	public static void setDataSrouceKey(BbObject bbobj, BaseModel model){
    	Class bbCls = bbobj.getClass();
    	Class modelCls = model.getClass();
    	String bbClsName = bbCls.getSimpleName();
    	String modelClsName = modelCls.getSimpleName();  	
		Method[] methods = bbCls.getDeclaredMethods(); 
		String setMethodName = "set" + "DataSourceId";
		for (int j = 0; j < methods.length; j++) { 
            if (methods[j].getName().equalsIgnoreCase(setMethodName)) {
                setMethodName = methods[j].getName(); 
            }
        }	
		Method setMethod;
		//load from configure file
		String loadKey = bbClsName+"."+modelClsName;
		DataSourceModel dsModel = findDataSourceModelByClsNames(bbClsName,modelClsName);
		getValuePairByType(dsModel, model);	
		DataSource ds = DataSourceUtil.createOrLoad(dataSourceId, description);
		try {
			setMethod = bbCls.getMethod(setMethodName, Id.class);
			setMethod.invoke(bbobj, ds.getId());
		} catch (Exception e) {
			logger.info("error in setting datasourcekey to "+bbClsName);
		}
    }
        private static void getValuePairByType(DataSourceModel dsModel, BaseModel model){
    	SourceType st = dsModel.getSourceType();
    	if(st==SourceType.MAPTYPE){
    		getValueFromMapType(dsModel,model);
    	}else if(st==SourceType.RENDERTYPE){
    		getValueFromRenderType(dsModel,model);
    	}else if(st==SourceType.RAWTYPE){
    		getValueFromRawtype(dsModel);
    	}
    }
    
    private static void getValueFromRawtype(DataSourceModel dsModel){
    	dataSourceId = dsModel.getRawSourceId();
    	description = dsModel.getRawDescription();
    }
    
    private static void getValueFromMapType(DataSourceModel dsModel, BaseModel model){
    	String objAttribute = dsModel.getMapperAttribute();
    	Method[] getMethods = model.getClass().getDeclaredMethods(); 
    	String getMethodName = "get" + objAttribute;
		for(int i = 0; i < getMethods.length;i++){
			if (getMethods[i].getName().equalsIgnoreCase(getMethodName)) 
				getMethodName = getMethods[i].getName();
		}
		Method getMethod;
		try {
			getMethod = model.getClass().getMethod(getMethodName);
			dataSourceId = (String) getMethod.invoke(model);
		} catch (Exception e) {			
			e.printStackTrace();
		} 
		description = dsModel.getRawDescription();
    }
    
    private static void getValueFromRenderType(DataSourceModel dsModel, BaseModel model){
    	String objAttribute = dsModel.getRenderAttribute();
    	Method[] getMethods = model.getClass().getDeclaredMethods(); 
    	String getMethodName = "get" + objAttribute;
		for(int i = 0; i < getMethods.length;i++){
			if (getMethods[i].getName().equalsIgnoreCase(getMethodName)) 
				getMethodName = getMethods[i].getName();
		}
		Method getMethod;
		try {
			getMethod = model.getClass().getMethod(getMethodName);
			dataSourceId = (String) getMethod.invoke(model);
			Pattern pattern = Pattern.compile(dsModel.getRenderRules());
			Matcher matcher = pattern.matcher(dataSourceId);
			if(matcher.find())
				dataSourceId = matcher.group();
		} catch (Exception e) {
			e.printStackTrace();
		} 
		description = dsModel.getRawDescription();
    }
   
}
